#include "SelectStoredExpressionDlg.h"
#include <configmanager.h>
#include <wx/string.h>
#include <wx/intl.h>

const long SelectStoredExpressionDlg::ID_LISTBOX1 = wxNewId();
const long SelectStoredExpressionDlg::ID_STATICTEXT1 = wxNewId();
const long SelectStoredExpressionDlg::ID_TEXTCTRL1 = wxNewId();
const long SelectStoredExpressionDlg::ID_BUTTON1 = wxNewId();
const long SelectStoredExpressionDlg::ID_BUTTON2 = wxNewId();
const long SelectStoredExpressionDlg::ID_BUTTON3 = wxNewId();
const long SelectStoredExpressionDlg::ID_BUTTON4 = wxNewId();
const long SelectStoredExpressionDlg::ID_TIMER1 = wxNewId();

BEGIN_EVENT_TABLE( SelectStoredExpressionDlg, wxScrollingDialog )
END_EVENT_TABLE()

SelectStoredExpressionDlg::SelectStoredExpressionDlg( wxWindow* parent, const wxString& startingExpression ) {
  m_Expression = startingExpression;
  m_CacheChanged = false;
  BuildContent( parent );
  ReadExpressions();
  RecreateExpressionsList();
}

void SelectStoredExpressionDlg::BuildContent( wxWindow* parent ) {
  wxBoxSizer* BoxSizer3;
  wxBoxSizer* BoxSizer2;
  wxBoxSizer* BoxSizer1;
  wxStdDialogButtonSizer* StdDialogButtonSizer1;
  wxStaticBoxSizer* StaticBoxSizer1;
  Create( parent, wxID_ANY, _( "存储表达式" ), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER, _T( "wxID_ANY" ) );
  BoxSizer1 = new wxBoxSizer( wxVERTICAL );
  StaticBoxSizer1 = new wxStaticBoxSizer( wxVERTICAL, this, _( "存储表达式" ) );
  m_Expressions = new wxListBox( this, ID_LISTBOX1, wxDefaultPosition, wxSize( 292, 119 ), 0, 0, 0, wxDefaultValidator, _T( "ID_LISTBOX1" ) );
  StaticBoxSizer1->Add( m_Expressions, 1, wxALL | wxEXPAND, 5 );
  BoxSizer2 = new wxBoxSizer( wxHORIZONTAL );
  StaticText1 = new wxStaticText( this, ID_STATICTEXT1, _( "过滤器:" ), wxDefaultPosition, wxDefaultSize, 0, _T( "ID_STATICTEXT1" ) );
  BoxSizer2->Add( StaticText1, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, 5 );
  m_Filter = new wxTextCtrl( this, ID_TEXTCTRL1, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T( "ID_TEXTCTRL1" ) );
  BoxSizer2->Add( m_Filter, 1, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5 );
  StaticBoxSizer1->Add( BoxSizer2, 0, wxBOTTOM | wxEXPAND, 5 );
  BoxSizer3 = new wxBoxSizer( wxHORIZONTAL );
  Button1 = new wxButton( this, ID_BUTTON1, _( "New" ), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T( "ID_BUTTON1" ) );
  BoxSizer3->Add( Button1, 1, wxLEFT | wxALIGN_CENTER_VERTICAL, 5 );
  Button2 = new wxButton( this, ID_BUTTON2, _( "Clone" ), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T( "ID_BUTTON2" ) );
  BoxSizer3->Add( Button2, 1, wxLEFT | wxALIGN_CENTER_VERTICAL, 5 );
  Button3 = new wxButton( this, ID_BUTTON3, _( "Modify" ), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T( "ID_BUTTON3" ) );
  BoxSizer3->Add( Button3, 1, wxLEFT | wxALIGN_CENTER_VERTICAL, 5 );
  Button4 = new wxButton( this, ID_BUTTON4, _( "Delete" ), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T( "ID_BUTTON4" ) );
  BoxSizer3->Add( Button4, 1, wxLEFT | wxALIGN_CENTER_VERTICAL, 5 );
  StaticBoxSizer1->Add( BoxSizer3, 0, wxBOTTOM | wxRIGHT | wxEXPAND, 5 );
  BoxSizer1->Add( StaticBoxSizer1, 1, wxALL | wxEXPAND, 5 );
  StdDialogButtonSizer1 = new wxStdDialogButtonSizer();
  StdDialogButtonSizer1->AddButton( new wxButton( this, wxID_OK, wxEmptyString ) );
  StdDialogButtonSizer1->AddButton( new wxButton( this, wxID_CANCEL, wxEmptyString ) );
  StdDialogButtonSizer1->Realize();
  BoxSizer1->Add( StdDialogButtonSizer1, 0, wxBOTTOM | wxLEFT | wxRIGHT | wxEXPAND, 5 );
  SetSizer( BoxSizer1 );
  Timer1.SetOwner( this, ID_TIMER1 );
  BoxSizer1->Fit( this );
  BoxSizer1->SetSizeHints( this );
  Connect( ID_LISTBOX1, wxEVT_COMMAND_LISTBOX_SELECTED, ( wxObjectEventFunction )&SelectStoredExpressionDlg::Onm_ExpressionsSelect );
  Connect( ID_LISTBOX1, wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, ( wxObjectEventFunction )&SelectStoredExpressionDlg::Onm_ExpressionsDClick );
  Connect( ID_TEXTCTRL1, wxEVT_COMMAND_TEXT_UPDATED, ( wxObjectEventFunction )&SelectStoredExpressionDlg::Onm_FilterText );
  Connect( ID_TEXTCTRL1, wxEVT_COMMAND_TEXT_ENTER, ( wxObjectEventFunction )&SelectStoredExpressionDlg::Onm_FilterTextEnter );
  Connect( ID_BUTTON1, wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&SelectStoredExpressionDlg::OnButton1Click );
  Connect( ID_BUTTON2, wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&SelectStoredExpressionDlg::OnButton2Click );
  Connect( ID_BUTTON3, wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&SelectStoredExpressionDlg::OnButton3Click );
  Connect( ID_BUTTON4, wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&SelectStoredExpressionDlg::OnButton4Click );
  Connect( ID_TIMER1, wxEVT_TIMER, ( wxObjectEventFunction )&SelectStoredExpressionDlg::OnTimer1Trigger );
  Connect( wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&SelectStoredExpressionDlg::OnOkClick );
  Connect( wxID_CANCEL, wxEVT_COMMAND_BUTTON_CLICKED, ( wxObjectEventFunction )&SelectStoredExpressionDlg::OnCancelClick );
}

SelectStoredExpressionDlg::~SelectStoredExpressionDlg() {
}

void SelectStoredExpressionDlg::ReadExpressions() {
  ConfigManager* mgr = Manager::Get()->GetConfigManager( _T( "lib_finder" ) );
  const wxString basePath = _T( "/storedexpressions" );
  wxArrayString keys = mgr->EnumerateSubPaths( basePath );
  for( size_t i = 0; i < keys.Count(); ++i ) {
    wxString path = basePath + _T( '/' ) + keys[i] + _T( '/' );
    wxString name = mgr->Read( path + _T( "name" ) );
    wxString value = mgr->Read( path + _T( "value" ) );
    if( !name.IsEmpty() && !value.IsEmpty() ) {
      m_Cache[ name ] = value;
    }
  }
}

void SelectStoredExpressionDlg::StoreExpressions() {
  ConfigManager* mgr = Manager::Get()->GetConfigManager( _T( "lib_finder" ) );
  const wxString basePath = _T( "/storedexpressions" );
  mgr->DeleteSubPath( _T( "/storedexpressions" ) );
  int index = 0;
  for( CacheT::iterator i = m_Cache.begin(); i != m_Cache.end(); ++i ) {
    wxString path = basePath + _T( '/' ) + wxString::Format( _T( "expr_%d" ), index++ ) + _T( '/' );
    mgr->Write( path + _T( "name" ),  i->first );
    mgr->Write( path + _T( "value" ), i->second );
  }
}

void SelectStoredExpressionDlg::RecreateExpressionsList( const wxString& selectionHint ) {
  m_Expressions->Clear();
  wxString filter = m_Filter->GetValue();
  for( CacheT::iterator i = m_Cache.begin(); i != m_Cache.end(); ++i ) {
    const wxString& name = i->first;
    const wxString& value = i->second;
    if( filter.IsEmpty() || name.Find( filter ) != wxNOT_FOUND || value.Find( filter ) != wxNOT_FOUND ) {
      wxString final = wxString::Format( _T( "%s: %s" ), name.c_str(), value.c_str() );
      int thisIndex = m_Expressions->Append( final, new ListData( i ) );
      if( !selectionHint.IsEmpty() && name == selectionHint ) {
        m_Expressions->Select( thisIndex );
      }
    }
  }
  if( m_Expressions->GetCount() > 0 && m_Expressions->GetSelection() == wxNOT_FOUND ) {
    m_Expressions->SetSelection( 0 );
  }
}

void SelectStoredExpressionDlg::OnButton1Click( wxCommandEvent& ) {
  AddingExpression( wxEmptyString, m_Expression );
}

void SelectStoredExpressionDlg::AddingExpression( const wxString& defaultName, const wxString& defaultExpression ) {
  wxString name = defaultName;
  for( ;; ) {
    name = cbGetTextFromUser( _( "输入此表达式的名称" ), _( "新表达式" ), name );
    if( name.IsEmpty() ) {
      return;
    }
    if( m_Cache.find( name ) != m_Cache.end() ) {
      int ret = msging( _( "具有同名表达式存在 你想替换它吗 ?" ), _( "重复表达式" ), wxYES_NO | wxCANCEL, this );
      if( ret == wxID_CANCEL ) {
        return;
      }
      if( ret == wxID_YES ) {
        break;
      }
    } else {
      break;
    }
  }
  wxString value = cbGetTextFromUser( _( "输入表达式" ), _( "新表达式" ), defaultExpression );
  if( value.IsEmpty() ) {
    return;
  }
  wxString filter = m_Filter->GetValue();
  if( !filter.IsEmpty() && name.Find( filter ) == wxNOT_FOUND && value.Find( filter ) == wxNOT_FOUND ) {
    m_Filter->ChangeValue( wxEmptyString );
  }
  m_Cache[ name ] = value;
  m_CacheChanged = true;
  RecreateExpressionsList( name );
}

void SelectStoredExpressionDlg::Onm_ExpressionsSelect( wxCommandEvent& ) {
}

void SelectStoredExpressionDlg::OnOkClick( wxCommandEvent& event ) {
  if( m_Expressions->GetSelection() == wxNOT_FOUND ) {
    return;
  }
  StoreExpressionsQuery();
  m_Expression = ( ( ListData* )m_Expressions->GetClientObject( m_Expressions->GetSelection() ) )->GetValue();
  event.Skip();
}

void SelectStoredExpressionDlg::OnCancelClick( wxCommandEvent& event ) {
  StoreExpressionsQuery();
  event.Skip();
}

void SelectStoredExpressionDlg::StoreExpressionsQuery() {
  if( m_CacheChanged ) {
    int ret = msging( _( "表达式已更改 是否保存它们?\n" ), _( "变更表达式" ), wxYES_NO );
    if( ret == wxID_YES ) {
      StoreExpressions();
    }
  }
  m_CacheChanged = false;
}

void SelectStoredExpressionDlg::OnButton2Click( wxCommandEvent& ) {
  ListData* data = GetSelection();
  if( !data ) {
    return;
  }
  AddingExpression( wxString::Format( _( "Copy of %s" ), data->GetKey().c_str() ), data->GetValue() );
}

SelectStoredExpressionDlg::ListData * SelectStoredExpressionDlg::GetSelection() {
  if( m_Expressions->GetSelection() == wxNOT_FOUND ) {
    return 0;
  }
  return ( ListData* )m_Expressions->GetClientObject( m_Expressions->GetSelection() );
}


void SelectStoredExpressionDlg::OnButton3Click( wxCommandEvent& ) {
  ListData* data = GetSelection();
  if( !data ) {
    return;
  }
  wxString value = cbGetTextFromUser( _( "输入新表达式" ), _( "修改表达式" ), data->GetValue() );
  wxString name = data->GetKey();
  if( value.IsEmpty() ) {
    return;
  }
  wxString filter = m_Filter->GetValue();
  if( !filter.IsEmpty() && name.Find( filter ) == wxNOT_FOUND && value.Find( filter ) == wxNOT_FOUND ) {
    m_Filter->ChangeValue( wxEmptyString );
  }
  m_Cache[ name ] = value;
  m_CacheChanged = true;
  RecreateExpressionsList( name );
}

void SelectStoredExpressionDlg::Onm_FilterText( wxCommandEvent& ) {
  Timer1.Start( 1000, true );
}

void SelectStoredExpressionDlg::Onm_FilterTextEnter( wxCommandEvent& ) {
  FilterUpdated();
}

void SelectStoredExpressionDlg::OnTimer1Trigger( wxTimerEvent& ) {
  FilterUpdated();
}

void SelectStoredExpressionDlg::FilterUpdated() {
  Timer1.Stop();
  ListData* data = GetSelection();
  wxString name;
  if( data ) {
    name = data->GetKey();
  }
  RecreateExpressionsList( name );
}

void SelectStoredExpressionDlg::OnButton4Click( wxCommandEvent& ) {
  ListData* data = GetSelection();
  if( !data ) {
    return;
  }
  m_Cache.erase( data->GetKey() );
  m_CacheChanged = true;
  RecreateExpressionsList();
}

void SelectStoredExpressionDlg::Onm_ExpressionsDClick( wxCommandEvent& event ) {
  OnOkClick( event );
  EndDialog( wxID_OK );
}
